#include "lsv_rcache.h"
#include "lsv_log.h"
#include "lsv_volume.h"
#include "volume_proto.h"
#include "list.h"

int lsv_rcache_load_pages(lsv_volume_proto_t *volume_proto, lsv_u32_t chunk_id,
                lsv_s32_t chunk_offset,lsv_u64_t off, lsv_s32_t size, buffer_t *append_buf){
        lsv_s32_t err = 0;
        lsv_rcache_t *rcache = (lsv_rcache_t *)volume_proto->rcache;

        DINFO("off %llu chunk_id %u chunk_off %d size %d\n", (LLU)off, chunk_id, chunk_offset, size);

        YASSERT(LSV_CHUNK_NULL != chunk_id);

        //避免load多个chunk，不在检查page 和 l2_cache的索引项
        err = lsv_rcache_chunk_hash_index_lookup(volume_proto, chunk_id, chunk_offset, off, size, append_buf);
        if(err == size){
                volume_proto->read_rc_hit++;
		rcache->chunk_hit_cnt ++;
                return err;
        }

        volume_proto->read_rc_miss++;

        //TODO 如果LSV_RCACHE_CHUNK_MAX > 0,即相当于在内存中分配一定内存用于缓存读出来的chunk，那么ssd中的chunk空间，用于缓存内存中换出的chunk即可

        DINFO("request page not in readcache, call lsv_log_slog_read\n");
	lsv_s8_t *buf = malloc(size);
	if(NULL == buf){
		DERROR("malloc for buf failed\n");
		err = -ENOMEM;
		return err;
	}

        err = lsv_rcache_read_data(volume_proto, buf, chunk_id, chunk_offset, size);
        if(err){
                DERROR("call lsv_rcache_read_read read chunk_id[%u] chunk_off[%d] size[%d] error:%d\n", chunk_id, chunk_offset, size, err);
                return err;
        }
	
        // 该页加入page cache
        mbuffer_appendmem(append_buf, buf, size);
	
	for(int i = 0; i < size/LSV_PAGE_SIZE; i++){
		lsv_rcache_pu_insert(volume_proto, 
					chunk_id, 
					chunk_offset + i * LSV_PAGE_SIZE, 
					off + i * LSV_PAGE_SIZE, LSV_PAGE_SIZE, 
					buf + i * LSV_PAGE_SIZE);
	}

        DINFO("read chunk_id: %u , chunk_off: %d, size: %d, return size: %d\n", chunk_id, chunk_offset, size, size);

        return size;
}
